package skipset

import (
	"github.com/DiracLee/skiplist-go/internal/bitmap"
	"sync"
	"unsafe"
)

const (
	fullyLinked bitmap.Bits = 1 << iota // 000...01, 本结点所有 next 都已连接
	marked                              // 000...10，是否被打标
)

type skipNode struct {
	value  int64         // 结点值
	next   pointerArray  // 下一个结点
	mtx    sync.Mutex    // value 和 next 构成一个不可分单元
	states bitmap.Bitmap // 结点状态
	height uint32        // 本节点的高度
}

// 创建节点
func newSkipNode(value int64, height int) *skipNode {
	return &skipNode{
		value:  value,
		height: uint32(height),
	}
}

// 读取第 l 层的 next
func (node *skipNode) loadNext(l int) *skipNode {
	return (*skipNode)(node.next.load(l))
}

// 存储第 l 层的 next
func (node *skipNode) storeNext(l int, p *skipNode) {
	node.next.store(l, unsafe.Pointer(p))
}

// 原子读取第 l 层的 next
func (node *skipNode) atomicLoadNext(l int) *skipNode {
	return (*skipNode)(node.next.atomicLoad(l))
}

// 原子存储第 l 层的 next
func (node *skipNode) atomicStoreNext(l int, p *skipNode) {
	node.next.atomicStore(l, unsafe.Pointer(p))
}

// 值比较：<
func (node *skipNode) lessThan(value int64) bool {
	return node.value < value
}

// 值比较：>
func (node *skipNode) greaterThan(value int64) bool {
	return node.value > value
}

// 值比较：==
func (node *skipNode) equalTo(value int64) bool {
	return node.value == value
}

// 将 highestLocked 及以下的前驱结点解锁，注意 go 的锁不可重入
func unlockInt64(prevs [maxHeight]*skipNode, highestLocked int) {
	var upperPrev *skipNode
	for l := highestLocked; l >= 0; l-- {
		prev := prevs[l]
		if prev != upperPrev { // golang 锁不可重入
			prev.mtx.Unlock()
			upperPrev = prev
		}
	}
}
